use aarch64_define::{
    MT_DEVICE_nGnRE, MT_NORMAL, PA_BITS, PAGE_SIZE, PGD_SHIFT, PGD_SIZE, PGD_TABLE_PXN,
    PGD_TYPE_TABLE, PMD_SHIFT, PMD_SIZE, PMD_TABLE_PXN, PMD_TYPE_TABLE, PTE_SHIFT, PTRS_PER_PGD,
    PTRS_PER_PMD, PTRS_PER_PTE, PTRS_PER_PUD, PUD_SHIFT, PUD_SIZE, PUD_TABLE_PXN, PUD_TYPE_TABLE,
};

pub(super) const ARCH_PA_BITS: usize = PA_BITS;

pub(super) const ARCH_PAGE_SIZE: usize = PAGE_SIZE;
pub(super) const ARCH_PAGE_SHIFT: usize = PTE_SHIFT;
pub(super) const ARCH_PAGE_PTRS: usize = PTRS_PER_PTE;

pub(super) const ARCH_PMD_SIZE: usize = PMD_SIZE;
pub(super) const ARCH_PMD_SHIFT: usize = PMD_SHIFT;
pub(super) const ARCH_PMD_PTRS: usize = PTRS_PER_PMD;

pub(super) const ARCH_PUD_SIZE: usize = PUD_SIZE;
pub(super) const ARCH_PUD_SHIFT: usize = PUD_SHIFT;
pub(super) const ARCH_PUD_PTRS: usize = PTRS_PER_PUD;

pub(super) const ARCH_PGD_SIZE: usize = PGD_SIZE;
pub(super) const ARCH_PGD_SHIFT: usize = PGD_SHIFT;
pub(super) const ARCH_PGD_PTRS: usize = PTRS_PER_PGD;

pub(super) const ARCH_PGD_TYPE_TABLE: usize = PGD_TYPE_TABLE | PGD_TABLE_PXN;
pub(super) const ARCH_PUD_TYPE_TABLE: usize = PUD_TYPE_TABLE | PUD_TABLE_PXN;
pub(super) const ARCH_PMD_TYPE_TABLE: usize = PMD_TYPE_TABLE | PMD_TABLE_PXN;

// 页保护属性

const ARCH_PTE_VALID: usize = 1;
pub(crate) const ARCH_PTE_TYPE_PAGE: usize = 3;
const ARCH_PTE_USER: usize = 1 << 6; // AP[1]
const ARCH_PTE_RDONLY: usize = 1 << 7; // AP[2]
const ARCH_PTE_SHARED: usize = 3 << 8; // SH[1:0], inner shareable
const ARCH_PTE_AF: usize = 1 << 10; // Access Flag
const ARCH_PTE_NG: usize = 1 << 11; // nG
const ARCH_PTE_DBM: usize = 1 << 51; // Dirty Bit Management
const ARCH_PTE_PXN: usize = 1 << 53; // Privileged XN
const ARCH_PTE_UXN: usize = 1 << 54; // User XN

// 软件维护标记 [55-59] bit 可用
const ARCH_PTE_WRITE: usize = ARCH_PTE_DBM; // 软件写标记
const ARCH_PTE_PROT_NONE: usize = 1 << 58;

const fn arch_pte_attrindx(t: usize) -> usize {
    t << 2
}

// 段保护属性

const ARCH_PMD_SECT_VALID: usize = 1 << 0;
pub(crate) const ARCH_PMD_TYPE_SECT: usize = 1 << 0;
const ARCH_PMD_SECT_USER: usize = 1 << 6; // AP[1]
const ARCH_PMD_SECT_RDONLY: usize = 1 << 7; // AP[2]
const ARCH_PMD_SECT_SHARED: usize = 3 << 8; // SH[1:0], inner shareable
const ARCH_PMD_SECT_AF: usize = 1 << 10; // Access Flag
const ARCH_PMD_SECT_NG: usize = 1 << 11; // nG
const ARCH_PMD_SECT_DBM: usize = 1 << 51; // Dirty Bit Management
const ARCH_PMD_SECT_PXN: usize = 1 << 53; // Privileged XN
const ARCH_PMD_SECT_UXN: usize = 1 << 54; // User XN

// 软件维护标记 [55-59] bit 可用
const ARCH_PMD_SECT_WRITE: usize = ARCH_PMD_SECT_DBM; // 软件写标记
const ARCH_PMD_SECT_PROT_NONE: usize = 1 << 58;

const fn arch_pmd_attrindx(t: usize) -> usize {
    t << 2
}

// 小页默认保护属性
const _PROT_DEFAULT: usize = ARCH_PTE_TYPE_PAGE | ARCH_PTE_AF | ARCH_PTE_SHARED;

// 普通小页默认保护属性
const _PAGE_DEFAULT: usize = _PROT_DEFAULT | arch_pte_attrindx(MT_NORMAL);
// 设备小页默认保护属性
const _DEVICE_DEFAULT: usize = _PROT_DEFAULT | arch_pte_attrindx(MT_DEVICE_nGnRE);

// 普通小页无效
pub(super) const ARCH_PAGE_NONE: usize = (_PAGE_DEFAULT & !ARCH_PTE_VALID)
    | ARCH_PTE_PROT_NONE
    | ARCH_PTE_RDONLY
    | ARCH_PTE_NG
    | ARCH_PTE_PXN
    | ARCH_PTE_UXN;
// 普通小页用户可读可写不可执行
pub(super) const ARCH_PAGE_READWRITE: usize =
    _PAGE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_NG | ARCH_PTE_PXN | ARCH_PTE_UXN | ARCH_PTE_WRITE;
// 普通小页用户可读可写可执行
pub(super) const ARCH_PAGE_READWRITE_EXEC: usize =
    _PAGE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_NG | ARCH_PTE_PXN | ARCH_PTE_WRITE;
// 普通小页用户仅可读不可写不可执行
pub(super) const ARCH_PAGE_RDONLY: usize =
    _PAGE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_RDONLY | ARCH_PTE_NG | ARCH_PTE_PXN | ARCH_PTE_UXN;
// 普通小页用户仅可读可执行不可写
pub(super) const ARCH_PAGE_RDONLY_EXEC: usize =
    _PAGE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_RDONLY | ARCH_PTE_NG | ARCH_PTE_PXN;
// 普通小页用户仅可执行不可读可写
pub(super) const ARCH_PAGE_EXECONLY: usize =
    _PAGE_DEFAULT | ARCH_PTE_RDONLY | ARCH_PTE_NG | ARCH_PTE_PXN;

// 设备小页无效
pub(super) const ARCH_DEVICE_NONE: usize = (_DEVICE_DEFAULT & !ARCH_PTE_VALID)
    | ARCH_PTE_PROT_NONE
    | ARCH_PTE_RDONLY
    | ARCH_PTE_NG
    | ARCH_PTE_PXN
    | ARCH_PTE_UXN;
// 设备小页用户可读可写不可执行
pub(super) const ARCH_DEVICE_READWRITE: usize =
    _DEVICE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_NG | ARCH_PTE_PXN | ARCH_PTE_UXN | ARCH_PTE_WRITE;
// 设备小页用户仅可读不可写不可执行
pub(super) const ARCH_DEVICE_RDONLY: usize =
    _DEVICE_DEFAULT | ARCH_PTE_USER | ARCH_PTE_RDONLY | ARCH_PTE_NG | ARCH_PTE_PXN | ARCH_PTE_UXN;

// 大页默认保护属性
const _PROT_SECT_DEFAULT: usize = ARCH_PMD_TYPE_SECT | ARCH_PMD_SECT_AF | ARCH_PMD_SECT_SHARED;

// 普通大页默认保护属性
const _PAGE_SECTION_DEFAULT: usize = _PROT_SECT_DEFAULT | arch_pmd_attrindx(MT_NORMAL);
// 设备大页默认保护属性
const _DEVICE_SECTION_DEFAULT: usize = _PROT_SECT_DEFAULT | arch_pmd_attrindx(MT_DEVICE_nGnRE);

// 普通大页无效
pub(super) const ARCH_SECTION_PAGE_NONE: usize = (_PAGE_SECTION_DEFAULT & !ARCH_PMD_SECT_VALID)
    | ARCH_PMD_SECT_PROT_NONE
    | ARCH_PMD_SECT_RDONLY
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN;
// 普通小页用户可读可写不可执行
pub(super) const ARCH_SECTION_PAGE_READWRITE: usize = _PAGE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN
    | ARCH_PMD_SECT_WRITE;
// 普通小页用户可读可写可执行
pub(super) const ARCH_SECTION_PAGE_READWRITE_EXEC: usize = _PAGE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_WRITE;
// 普通小页用户仅可读不可写不可执行
pub(super) const ARCH_SECTION_PAGE_RDONLY: usize = _PAGE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_RDONLY
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN;
// 普通小页仅可读可执行不可写
pub(super) const ARCH_SECTION_PAGE_RDONLY_EXEC: usize = _PAGE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_RDONLY
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN;
// 普通小页仅可执行不可读可写
pub(super) const ARCH_SECTION_PAGE_EXECONLY: usize =
    _PAGE_SECTION_DEFAULT | ARCH_PMD_SECT_RDONLY | ARCH_PMD_SECT_NG | ARCH_PMD_SECT_PXN;

// 设备小页无效
pub(super) const ARCH_SECTION_DEVICE_NONE: usize = (_DEVICE_SECTION_DEFAULT & !ARCH_PMD_SECT_VALID)
    | ARCH_PMD_SECT_PROT_NONE
    | ARCH_PMD_SECT_RDONLY
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN;
// 设备小页用户可读可写不可执行
pub(super) const ARCH_SECTION_DEVICE_READWRITE: usize = _DEVICE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN
    | ARCH_PMD_SECT_WRITE;
// 设备小页用户仅可读不可写不可执行
pub(super) const ARCH_SECTION_DEVICE_RDONLY: usize = _DEVICE_SECTION_DEFAULT
    | ARCH_PMD_SECT_USER
    | ARCH_PMD_SECT_RDONLY
    | ARCH_PMD_SECT_NG
    | ARCH_PMD_SECT_PXN
    | ARCH_PMD_SECT_UXN;
